﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace SSP
{

    class SSPSprite : SSPNode
    {
        public Texture2D texture;
        int rows, columns, totalFrames;
        public readonly int width;
        public readonly int height;
        public int currentFrame;
        public bool flipX;
        public bool flipY;
        bool paused;
        public Color color;
        public readonly bool usesSpriteSheet;
        public readonly bool isAnimated;
        public double animationSpeed;
        public bool looping = true;
        double currentSpeedVar = 0;
        Rectangle sourceRect;
        SpriteEffects effect;
        public string tagName { get; set; }
        public bool isSpecial;

        public SSPSprite()
        {
        }

        public SSPSprite(string textureName)
        {
            texture = SSPDirector.Instance.gameInstance.Content.Load<Texture2D>(textureName);

            anchorPoint.X = texture.Width / 2;
            anchorPoint.Y = texture.Height / 2;

            position.X = 0;
            position.Y = 0;

            width = texture.Width;
            height = texture.Height;

            flipX = false;
            flipY = false;

            rows = 1;
            columns = 1;
            totalFrames = 1;
            currentFrame = 0;

            color = Color.White;
            paused = false;

            usesSpriteSheet = false;
            isAnimated = false;
        }

        public SSPSprite(string tag, string textureName)
        {
            texture = SSPDirector.Instance.gameInstance.Content.Load<Texture2D>(textureName);

            tagName = tag;

            anchorPoint.X = texture.Width / 2;
            anchorPoint.Y = texture.Height / 2;

            position.X = 0;
            position.Y = 0;

            width = texture.Width;
            height = texture.Height;

            flipX = false;
            flipY = false;

            rows = 1;
            columns = 1;
            totalFrames = 1;
            currentFrame = 0;

            color = Color.White;
            paused = false;

            usesSpriteSheet = false;
            isAnimated = false;
        }

        public SSPSprite(string textureName, int sheetRows, int sheetColumns, int startingFrame, double imageSpeed,bool loop)
        {
            texture = SSPDirector.Instance.gameInstance.Content.Load<Texture2D>(textureName);

            rows = sheetRows;
            columns = sheetColumns;
            totalFrames = rows * columns;

            width = texture.Width / columns;
            height = texture.Height / rows;

            anchorPoint.X = width / 2;
            anchorPoint.Y = height / 2;

            position.X = 0;
            position.Y = 0;

            flipX = false;
            flipY = false;

            paused = false;
            currentFrame = startingFrame;
            animationSpeed = (double)MathHelper.Clamp((float)imageSpeed, 0, 1);
            looping = loop;

            color = Color.White;

            usesSpriteSheet = true;
            isAnimated = true;
        }

        public SSPSprite(SSPSpriteSheet textureName, int x, int y, int w, int h)
        {
            texture = textureName.texture;

            rows = 1;
            columns = 1;
            totalFrames = 1;
            currentFrame = 0;

            width = w;
            height = h;

            anchorPoint.X = width / 2;
            anchorPoint.Y = height / 2;

            position.X = 0;
            position.Y = 0;

            flipX = false;
            flipY = false;

            sourceRect = new Rectangle(x, y, w, h);

            paused = false;

            color = Color.White;

            usesSpriteSheet = true;
            isAnimated = false;
        }

        public SSPSprite(SSPSprite sp)
        {
            texture = sp.texture;

            tagName = sp.tagName;

            rows = sp.rows;
            columns = sp.columns;
            totalFrames = sp.totalFrames;

            width = sp.width;
            height = sp.height;

            anchorPoint = sp.anchorPoint;

            position = sp.position;

            flipX = sp.flipX;
            flipY = sp.flipY;

            paused = sp.paused;
            currentFrame = sp.currentFrame;
            animationSpeed = sp.animationSpeed;
            looping = sp.looping;

            color = sp.color;

            usesSpriteSheet = sp.usesSpriteSheet;
            isAnimated = sp.isAnimated;
        }

        public SSPSprite(SSPSprite sp,int x, int y, float s)
        {
            texture = sp.texture;
            isSpecial = true;
            tagName = sp.tagName;

            rows = sp.rows;
            columns = sp.columns;
            totalFrames = sp.totalFrames;

            width = sp.width;
            height = sp.height;

            scale = new Vector2(s, s);
            anchorPoint = sp.anchorPoint;

            position = new Vector2(x,y);

            flipX = sp.flipX;
            flipY = sp.flipY;

            paused = sp.paused;
            currentFrame = sp.currentFrame;
            animationSpeed = sp.animationSpeed;
            looping = sp.looping;

            color = sp.color;

            usesSpriteSheet = sp.usesSpriteSheet;
            isAnimated = sp.isAnimated;
        }

        public override void draw()
        {
            //Console.WriteLine("Sprite Draw()");
            //Console.WriteLine("draw Sprite 0 {0}, AbsPos = {1},{2}  pos = {3}", scale.X, absolutePosition.X, absolutePosition.Y, position.X);
            if (flipX)
            {
                effect = SpriteEffects.FlipHorizontally;
            }
            else if (flipY)
            {
                effect = SpriteEffects.FlipVertically;
            }
            else
            {
                effect = SpriteEffects.None;
            }

            //SSPDirector.Instance.spriteBatchInstance.Draw(texture, absolutePosition, null, color, rotation, anchorPoint, scale, SpriteEffects.None, zOrder);
            if (isAnimated && usesSpriteSheet && visible)
            {
                
                SSPDirector.Instance.spriteBatchInstance.Draw(texture,
                new Rectangle((int)absolutePosition.X, (int)absolutePosition.Y, (int)(width * scale.X), (int)(height * scale.Y)),
                new Rectangle( (currentFrame % columns) * width,(currentFrame / columns) * height, width, height),
                color, rotation, anchorPoint, effect, zOrder);
                //Console.WriteLine("Drawing Animated Sprite");
            }
            else if (usesSpriteSheet && !isAnimated && visible)
            {
                SSPDirector.Instance.spriteBatchInstance.Draw(texture,
                new Rectangle((int)absolutePosition.X, (int)absolutePosition.Y, (int)(width * scale.X), (int)(height * scale.Y)),
                sourceRect,
                color, rotation, anchorPoint, effect, zOrder);
                //Console.WriteLine("Drawing Static Sheet Sprite - {0},{1},{2},{3}", sourceRect.X, sourceRect.Y, sourceRect.Width, sourceRect.Height);
            }
            else if ( visible ) 
            {
                SSPDirector.Instance.spriteBatchInstance.Draw(texture, 
                    new Rectangle((int)absolutePosition.X, (int)absolutePosition.Y, (int)(width * scale.X), (int)(height * scale.Y)),
                    new Rectangle(0, 0, width, height),
                    color, rotation, anchorPoint, effect, zOrder);
                //Console.WriteLine("draw Sprite 2 {0}, AbsPos = {1},{2}  pos = {3}", scale.X, absolutePosition.X, absolutePosition.Y, position.X );
                //Console.WriteLine("Drawing Static Sprite - {0},{1}",width,height);
            }

            foreach (SSPNode n in children)
            {
                n.draw();
            }
            
        }


        public override void update()
        {
            //Console.WriteLine("Sprite Update()");
            
            if (parent != null)
            {
                if (parent.isScene && !isSpecial)
                {

                    absolutePosition = position;
                }
                
            }
            else
            {
                if (!isSpecial)
                {
                    absolutePosition = Vector2.Add(position, parent.position);
                }

            }
            
           
            foreach (SSPNode n in children)
            {
                n.update();
            }

            if (!paused)
            {
                if (currentSpeedVar >= 1)
                {
                    currentFrame++;
                    currentSpeedVar = (1 - currentSpeedVar) + animationSpeed;
                }
                else
                {
                    currentSpeedVar += animationSpeed;
                }

                if (currentFrame == totalFrames)
                {
                    if (looping == true)
                    {
                        currentFrame = 0;
                    }
                }
            }
            
        }

        public void Pause()
        {
            paused = true;
        }

        public void Play()
        {
            paused = false;
        }


    }
}
